package cn.lyf.myblog.controller.api;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.*;
import static cn.lyf.myblog.controller.api.JsonUtils.*;

import java.util.*;
import java.io.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.ui.Model;
import cn.lyf.myblog.service.*;
import cn.lyf.myblog.mybatis.entity.*;
import org.springframework.web.bind.annotation.RequestMapping;

import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;

@Controller
public class BlogApi {
    @Autowired
    BlogService blogService;
    @Autowired
    LikeService likeService;
    @Autowired
    LabelService labelService;

    static String staticPath;
    static String dir = "/content/";
    static {
        try {
            staticPath = ResourceUtils.getURL("classpath:").getPath() + "static";
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @GetMapping("/blog/{id}")
    @ResponseBody
    JsonNode getBlog(@PathVariable Integer id) throws Exception {
        try {
            return blogService.getBlogInfo(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        ObjectNode res = mapper.createObjectNode();
        res.put("success", false);
        res.put("code", 464);
        res.put("message", "博客获取失败！");
        return res;
    }

    @PostMapping("/user/update/blog")
    @Transactional(rollbackFor = Exception.class)
    String updateBlog(@RequestParam Map<String, Object> map, Model model) throws Exception {
        ObjectNode msg = mapper.convertValue(map, ObjectNode.class);
        msg.put("path", staticPath);
        msg.put("dir",dir);
        blogService.updateBlog(msg);
        model.addAttribute("msg", "修改成功");
        return "/user/manage";
        // return blogService.updateBlog(msg);
    }

    @RequestMapping("/user/edit/{bid}")
    @Transactional(rollbackFor = Exception.class)
    String updateBlog(@PathVariable Integer bid, Model model) throws Exception {
        Blog blog = blogService.getBlogByBid(bid);
        String content = readArticle(staticPath + dir + blog.getUrl());
        blog.setContent(content);
        model.addAttribute("blog", blog);
        return "/user/update";
    }

    @RequestMapping("/user/del/{bid}")
    @Transactional(rollbackFor = Exception.class)
    String deleteBlog(@PathVariable Integer bid, Model model) throws Exception {
        ObjectNode msg = mapper.createObjectNode();
        msg.put("bid", bid);
        msg.put("path", staticPath);
        model.addAttribute("msg", getString(blogService.deleteBlog(msg), "/result/message"));
        return "/user/manage";
    }

    @PostMapping("/blog")
    @Transactional(rollbackFor = Exception.class)
    String publishBlog(@RequestParam Map<String, Object> map, Model model) throws Exception {
        ObjectNode msg = mapper.convertValue(map, ObjectNode.class);
        msg.put("name", UUID.randomUUID().toString().replaceAll("-", ""));
        msg.put("staticPath", staticPath);
        msg.put("dir", dir);
        blogService.upLoadBlog(msg);
        model.addAttribute("msg", "博客发布成功");
        return "/user/publish";
    }

    @PostMapping("/blog/like")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    JsonNode likeBlog(@RequestBody JsonNode json) throws Exception {
        ObjectNode res = mapper.createObjectNode();
        try {
            likeService.ins(json);
            res.put("success", true);
            res.put("code", 200);
            res.put("message", "点赞成功！");
        } catch (DuplicateKeyException e) {
            res.put("success", false);
            res.put("code", 464);
            res.put("message", "重复点赞！");
        }
        return res;
    }

    @DeleteMapping("/blog/like")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    JsonNode unlikeBlog(@RequestBody JsonNode json) throws Exception {
        ObjectNode res = mapper.createObjectNode();
        likeService.del(json);
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "取消点赞成功！");
        return res;
    }

    @RequestMapping("/blog/total/{uid}")
    @ResponseBody
    JsonNode getTotal(@PathVariable int uid) throws Exception {
        ObjectNode res = mapper.createObjectNode();
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "获取博客总数成功！");
        res.put("result", blogService.getSum(uid));
        return res;
    }

    @RequestMapping("/blog/list")
    @ResponseBody
    JsonNode getBlogList(@RequestBody JsonNode json) throws Exception {
        ObjectNode res = mapper.createObjectNode();
        try {
            res = blogService.getBlogLately(json.deepCopy());
        } catch (Exception e) {
            e.printStackTrace();
            res.put("success", false);
            res.put("code", 464);
            res.put("message", "获取博客列表失败！");
        }
        return res;
    }

    @RequestMapping("/toHtml/{url}")
    @ResponseBody
    public String toHtml(@PathVariable String url) throws Exception {
        HtmlRenderer renderer = HtmlRenderer.builder().build();
        Parser parser = Parser.builder().build();
        String content = readArticle(staticPath + dir + url);
        Node document = parser.parse(content);
        return renderer.render(document);
    }

    String readArticle(String str) throws Exception {
        BufferedReader in = new BufferedReader(new FileReader(new File(str)));
        StringBuffer sb = new StringBuffer();
        while ((str = in.readLine()) != null)
            sb.append(str).append('\n');
        in.close();
        return sb.toString();
    }

    @RequestMapping("/getArchives/{uid}")
    @ResponseBody
    JsonNode archives(@PathVariable Integer uid) throws Exception {
        return blogService.getArchives(uid);
    }

    @RequestMapping("/getBlogsByFavorites/{fid}")
    @ResponseBody
    JsonNode getBlogsByFavorites(@PathVariable Integer fid) throws Exception {
        return blogService.getBlogByFavorites(fid);
    }

    @RequestMapping("/getBlogsByLabel/{uid}/{lid}")
    @ResponseBody
    JsonNode getBlogsByLabel(@PathVariable Integer uid, @PathVariable Integer lid) throws Exception {
        return labelService.getBlogs(lid, uid);
    }

    @RequestMapping("/getLabels")
    @ResponseBody
    JsonNode getLabels() throws Exception {
        return labelService.getLabels();
    }

    @PostMapping({ "/search/{uid}", "/search" })
    @ResponseBody
    JsonNode search(@RequestBody JsonNode json, @PathVariable(required = false) Integer uid) throws Exception {
        ObjectNode res = mapper.createObjectNode();
        res.put("success", true);
        res.put("code", 200);
        String title = getString(json, "/title");
        String tags = getJsonNode(json, "/tags").toString();
        res.putPOJO("result", blogService.search(title, Arrays.asList(mapper.readValue(tags, String[].class)), uid));
        return res;
    }

}
